package com.xuecheng.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.content.model.TeachplanDTO;
import com.xuecheng.api.content.model.TeachplanMediaDTO;
import com.xuecheng.api.content.model.dto.CourseBaseDTO;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.enums.common.AuditEnum;
import com.xuecheng.common.enums.content.CourseAuditEnum;
import com.xuecheng.common.enums.content.TeachPlanEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.content.common.constant.ContentErrorCode;
import com.xuecheng.content.convert.CourseBaseConvert;
import com.xuecheng.content.convert.TeachplanConvert;
import com.xuecheng.content.convert.TeachplanMediaConvert;
import com.xuecheng.content.entity.CourseBase;
import com.xuecheng.content.entity.Teachplan;
import com.xuecheng.content.entity.TeachplanMedia;
import com.xuecheng.content.entity.ex.TeachplanNode;
import com.xuecheng.content.mapper.TeachplanMapper;
import com.xuecheng.content.service.CourseBaseService;
import com.xuecheng.content.service.TeachplanMediaService;
import com.xuecheng.content.service.TeachplanService;
import com.xuecheng.media.entity.Media;
import com.xuecheng.media.service.MediaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 课程计划 服务实现类
 * </p>
 */
@Service
public class TeachplanServiceImpl extends ServiceImpl<TeachplanMapper, Teachplan> implements TeachplanService {

    @Autowired
    private CourseBaseService courseBaseService;

    @Autowired
    private TeachplanMediaService teachplanMediaService;

    @Autowired
    private MediaService mediaService;
    //课程关联媒资
    @Transactional
    public TeachplanMediaDTO associateMedia(TeachplanMediaDTO dto, Long companyId) {
        if(ObjectUtils.isEmpty(companyId)){
            ExceptionCast.cast(CommonErrorCode.E_100108);
        }
        if( ObjectUtils.isEmpty(dto.getTeachplanId())
                || ObjectUtils.isEmpty(dto.getMediaId())){
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        //判断课程计划
        Teachplan teachplan = this.getById(dto.getTeachplanId());
        //课程计划是否存在
        if(ObjectUtils.isEmpty(teachplan)){
            ExceptionCast.cast(ContentErrorCode.E_120402);
        }
        //课程计划是否是第三级
        if(!TeachPlanEnum.THIRD_LEVEL.equals(teachplan.getGrade())){
            ExceptionCast.cast(ContentErrorCode.E_120410);
        }
        dto.setCourseId(teachplan.getCourseId());

        //判断课程
        CourseBaseDTO course = courseBaseService.getByCourseId(dto.getCourseId(), companyId);
        CourseBase courseBase = CourseBaseConvert.INSTANCE.dto2entity(course);

        //判断媒资是否存在且属于同一家机构
        LambdaQueryWrapper<Media> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Media::getId,dto.getMediaId());
        wrapper.eq(Media::getCompanyId,companyId);
        Media media = mediaService.getOne(wrapper);
        //如果没拿到媒资信息，说明媒资信息不存在
        if(ObjectUtils.isEmpty(media)){
            throw new RuntimeException("媒资信息不存在");
        }
        if(!companyId.equals(media.getCompanyId())){
            ExceptionCast.cast(CommonErrorCode.E_100108);
        }
        //媒资的审核状态是否是已经审核通过的
        if(!(AuditEnum.AUDIT_PASTED_STATUS.getCode().equals(media.getAuditStatus()))){
            ExceptionCast.cast(CommonErrorCode.E_100107);
        }
        //保存课程计划和媒资信息
        dto.setMediaFilename(media.getFilename());
        dto.setCoursePubId(courseBase.getCoursePubId());
        dto.setCourseId(courseBase.getId());
        TeachplanMedia teachplanMedia = TeachplanMediaConvert.INSTANCE.dto2entity(dto);
        //添加之前判断是修改还是新增
        LambdaQueryWrapper<TeachplanMedia> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TeachplanMedia::getTeachplanId,teachplan.getId());
        queryWrapper.eq(TeachplanMedia::getCourseId,courseBase.getId());
        TeachplanMedia resultTeachplanMedia = teachplanMediaService.getOne(queryWrapper);
        boolean result = false;
        //没查到就是添加，查到了就是修改
        if(ObjectUtils.isEmpty(resultTeachplanMedia)){
            result = teachplanMediaService.save(teachplanMedia);
        }else {
            LambdaUpdateWrapper<TeachplanMedia> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(TeachplanMedia::getMediaId,dto.getMediaId());
            updateWrapper.set(TeachplanMedia::getMediaFilename,dto.getMediaFilename());
            result = teachplanMediaService.update(updateWrapper);
        }
        if(!result){
            ExceptionCast.cast(ContentErrorCode.E_120411);
        }
        TeachplanMedia po = teachplanMediaService.getOne(queryWrapper);
        TeachplanMediaDTO teachplanMediaDTO = TeachplanMediaConvert.INSTANCE.entity2dto(po);
        return teachplanMediaDTO;
    }
    //树形查看课程内所有章节
    public TeachplanDTO queryTreeNodesByCourseId(Long courseId, Long companyId) {
        //判断课程是否存在
        courseBaseService.getByCourseId(courseId,companyId);
        LambdaQueryWrapper<Teachplan> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Teachplan::getCourseId,courseId);
        wrapper.orderBy(true,true,Teachplan::getGrade,Teachplan::getOrderby);
        List<Teachplan> list = this.list(wrapper);
        List<TeachplanNode> teachplanNodes = TeachplanConvert.INSTANCE.entitys2nodes(list);
        TeachplanDTO teachplanDTO = null;
        if(!CollectionUtils.isEmpty(teachplanNodes)){
            TeachplanNode teachplanNode = teachplanNodes.remove(0);
            generateTreeNodes(teachplanNode,teachplanNodes);
            teachplanDTO = TeachplanConvert.INSTANCE.node2dto(teachplanNode);
        }else{
            teachplanDTO = new TeachplanDTO();
        }
        return teachplanDTO;
/*        wrapper.eq(Teachplan::getParentid,0);
        Teachplan one = this.getOne(wrapper);
        if (ObjectUtils.isEmpty(one)){
            return null;
        }
        TeachplanDTO teachplanDTO = TeachplanConvert.INSTANCE.entity2dto(one);
        //找子章节
        LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Teachplan::getParentid,one.getId());
        //二级子章节集合
        List<Teachplan> list = this.list(queryWrapper);
        List<TeachplanDTO> dtolist2 =new ArrayList<>();
        //遍历二级找第三级子章节集合
        for (Teachplan teachplan : list) {
            Long id = teachplan.getId();
            LambdaQueryWrapper<Teachplan> wrapper1 = new LambdaQueryWrapper<>();
            wrapper1.eq(Teachplan::getParentid,id);
            //单个二级内的三级集合
            List<TeachplanDTO> dtolist3 =new ArrayList<>();
            //三级
            List<Teachplan> list1 = this.list(wrapper1);
            for (Teachplan teachplan1 : list1) {
                TeachplanDTO dto = TeachplanConvert.INSTANCE.entity2dto(teachplan1);
                dtolist3.add(dto);
            }
            TeachplanDTO dto = TeachplanConvert.INSTANCE.entity2dto(teachplan);
            dto.setTeachPlanTreeNodes(dtolist3);
            dtolist2.add(dto);
        }
        teachplanDTO.setTeachPlanTreeNodes(dtolist2);
        return teachplanDTO;*/
    }

    //添加或者修改课程中的子章节
    @Transactional
    public TeachplanDTO createOrModifyTeachPlan(TeachplanDTO dto, Long companyId) {
        TeachplanDTO teachplanDTO=null;
        Long teachPlanId = dto.getTeachPlanId();
        if (teachPlanId==null){
            teachplanDTO=createTeachplan(dto,companyId);
        }
        else {
            teachplanDTO=mofifyTeachplan(dto,companyId);
        }
        return teachplanDTO;
    }

    //修改课程中的子章节

    private TeachplanDTO mofifyTeachplan(TeachplanDTO dto, Long companyId) {
        Long courseId = dto.getCourseId();
        //判断条件
        CourseBaseDTO baseDTO = courseBaseService.getByCourseId(courseId, companyId);
//        if (one.getCompanyId()!=companyId){
//            throw new RuntimeException("两次公司id不一致");
//        }
        LambdaUpdateWrapper<Teachplan> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(Teachplan::getPname,dto.getPname());
        updateWrapper.set(Teachplan::getChangeDate,dto.getChangeDate());

        updateWrapper.set(Teachplan::getIsPreview,dto.getIsPreview());
        updateWrapper.set(Teachplan::getStartTime,dto.getStartTime());
        updateWrapper.set(Teachplan::getEndTime,dto.getEndTime());
        updateWrapper.eq(Teachplan::getId,dto.getTeachPlanId());
        boolean update = this.update(updateWrapper);
        if (!update){
            throw new RuntimeException("修改子章节失败");
        }
//        LambdaUpdateWrapper<Teachplan> updateWrapper1 = new LambdaUpdateWrapper<>();
        LambdaQueryWrapper<Teachplan> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Teachplan::getId,dto.getTeachPlanId());
        Teachplan teachplan = this.getOne(wrapper);
        if (teachplan.getId()==null){
            throw new RuntimeException("子章节id不能为空");
        }
        if (StringUtil.isEmpty(teachplan.getPname())){
            throw new RuntimeException("子章节名称不能为空");
        }
        TeachplanDTO resultDTO = TeachplanConvert.INSTANCE.entity2dto(teachplan);
        return resultDTO;
    }

    //添加课程中的子章节
    private TeachplanDTO createTeachplan(TeachplanDTO dto, Long companyId) {
        if (StringUtil.isBlank(dto.getPname())|| ObjectUtils.isEmpty(dto.getCourseId())|| ObjectUtils.isEmpty(companyId))
        {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        Long courseId = dto.getCourseId();
        LambdaQueryWrapper<CourseBase> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CourseBase::getId,courseId);
        CourseBase one = courseBaseService.getOne(queryWrapper);
        if (one==null){
            ExceptionCast.cast(ContentErrorCode.E_120013);
        }
        if (one.getStatus()==0){
            ExceptionCast.cast(ContentErrorCode.E_120013);
        }
//        if (one.getCompanyId()!=companyId){
//            throw new RuntimeException("两次公司id不一致");
//        }
        if (one.getAuditStatus().equals(CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode())||one.getAuditStatus().equals(CourseAuditEnum.AUDIT_PASTED_STATUS.getCode())||one.getAuditStatus().equals(CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode())){
            throw new RuntimeException("课程已提交或审核通过或者已经发布哦！不能删除");
        }
        String auditStatus = one.getAuditStatus();
        if (CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(auditStatus)
        ) {
            ExceptionCast.cast(ContentErrorCode.E_120015);
        }
        CourseBaseDTO byCourseId = courseBaseService.getByCourseId(courseId, companyId);
        Teachplan parentNode = getParentDate(dto,byCourseId);
        //        通过父级数据：grade+1=当前数据的级别
        Integer grade = parentNode.getGrade();
        dto.setGrade(1+grade);
        //        通过父级数据：parentId
        dto.setParentid(parentNode.getId());

        LambdaQueryWrapper<Teachplan> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(Teachplan::getParentid, parentNode.getId());
        int count = this.count(queryWrapper1);
        dto.setOrderby(count+1);
        Teachplan teachplan = TeachplanConvert.INSTANCE.dto2entity(dto);

        boolean result = this.save(teachplan);

        if (!result) {
            ExceptionCast.cast(ContentErrorCode.E_120407);
        }
        // 5.判断操作的结果并返回数据dto
        Teachplan po = this.getById(teachplan.getId());
        TeachplanDTO resultDTO = TeachplanConvert.INSTANCE.entity2dto(po);
        return resultDTO;
    }
    private Teachplan getParentDate(TeachplanDTO dto, CourseBaseDTO courseBase) {

        Long parentid = dto.getParentid();
        if (ObjectUtils.isEmpty(parentid)) {
            // 根据courseId和parentid=0来查找一个课程下一级课程计划数据
            LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Teachplan::getCourseId,courseBase.getCourseBaseId());
            queryWrapper.eq(Teachplan::getParentid, TeachPlanEnum.FIRST_PARENTID_FLAG);
            Teachplan parentNode = this.getOne(queryWrapper);
            if (ObjectUtils.isEmpty(parentNode)) {
                // 在后端自动创建课程计划一级数据
                parentNode = new Teachplan();
                parentNode.setPname(courseBase.getName());
                parentNode.setParentid(new Long(TeachPlanEnum.FIRST_PARENTID_FLAG));
                parentNode.setGrade(TeachPlanEnum.FIRST_LEVEL);
                parentNode.setOrderby(TeachPlanEnum.FIRST_LEVEL);
                parentNode.setCourseId(courseBase.getCourseBaseId());
                boolean result = this.save(parentNode);
                if (!result) {
                    throw new RuntimeException("保存一级项目计划失败");
                }
            }
            return parentNode;
        } else {
            // 获得三级父级数据
            LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Teachplan::getId, parentid);
            queryWrapper.eq(Teachplan::getCourseId, courseBase.getCourseBaseId());

            Teachplan parentNode = this.getOne(queryWrapper);
            if (ObjectUtils.isEmpty(parentNode)) {
                ExceptionCast.cast(ContentErrorCode.E_120408);
            }
            return parentNode;
        }
    }

    //删除章节
    @Override
    public void removeTeachPlan(Long teachPlanId, Long companyId) {
        LambdaQueryWrapper<Teachplan> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Teachplan::getId,teachPlanId);
        Teachplan one = this.getOne(wrapper);
        if (ObjectUtils.isEmpty(one)){
            throw new RuntimeException("该子章节id不存在");
        }
        LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Teachplan::getParentid,teachPlanId);
        List<Teachplan> list = this.list(queryWrapper);
        if (!ObjectUtils.isEmpty(list)){
            throw new RuntimeException("该章节下有子章节，不能直接删除");
        }
        courseBaseService.getByCourseId(one.getCourseId(),companyId);
        this.removeById(teachPlanId);
    }
    /*
     * 递归生成课程计划树形结构
     * */
    private void generateTreeNodes(TeachplanNode rootNode, List<TeachplanNode> nodes) {
        if (CollectionUtils.isEmpty(rootNode.getChildrenNodes())) {
            ArrayList<TeachplanNode> childrens = new ArrayList<>();
            rootNode.setChildrenNodes(childrens);
        }
        for (TeachplanNode node : nodes) {
            if (ObjectUtils.nullSafeEquals(rootNode.getId(), node.getParentid())) {
                rootNode.getChildrenNodes().add(node);
                if (!(TeachPlanEnum.THIRD_LEVEL.equals(node.getGrade()))) {
                    generateTreeNodes(node, nodes);
                } else {
                    // 如果课程是第三级，查询课程计划是否有关联的媒资信息
                    LambdaQueryWrapper<TeachplanMedia> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.eq(TeachplanMedia::getTeachplanId, node.getId());
                    TeachplanMedia teachplanMedia = teachplanMediaService.getOne(queryWrapper);
                    node.setTeachplanMedia(teachplanMedia);
                }
            }
        }
    }
}